/**
 * 贴图配置文件辅助函数
 * 每个贴图独立保存配置文件，类似模型配置管理
 */

const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');

/**
 * 读取单个贴图的完整配置
 * @param {string} texturesDir - 贴图目录路径
 * @param {string} textureId - 贴图ID
 * @returns {Promise<Object|null>} 贴图配置对象，如果不存在返回null
 */
async function readTextureConfig(texturesDir, textureId) {
    const configPath = path.join(texturesDir, `${textureId}.json`);
    
    try {
        const data = await fs.readFile(configPath, 'utf-8');
        return JSON.parse(data);
    } catch (error) {
        return null;
    }
}

/**
 * 写入单个贴图的完整配置
 * @param {string} texturesDir - 贴图目录路径
 * @param {string} textureId - 贴图ID
 * @param {Object} textureData - 贴图配置数据
 */
async function writeTextureConfig(texturesDir, textureId, textureData) {
    const configPath = path.join(texturesDir, `${textureId}.json`);
    textureData.updatedAt = new Date().toISOString();
    await fs.writeFile(configPath, JSON.stringify(textureData, null, 2), 'utf-8');
}

/**
 * 删除单个贴图的配置文件
 * @param {string} texturesDir - 贴图目录路径
 * @param {string} textureId - 贴图ID
 */
async function deleteTextureConfig(texturesDir, textureId) {
    const configPath = path.join(texturesDir, `${textureId}.json`);
    
    try {
        await fs.unlink(configPath);
    } catch (error) {
        // 文件可能不存在，忽略错误
    }
}

/**
 * 获取所有贴图的完整配置（从各自的配置文件）
 * @param {string} texturesDir - 贴图目录路径
 * @returns {Promise<Array>} 贴图配置数组
 */
async function getAllTextures(texturesDir) {
    try {
        // 确保目录存在
        if (!fsSync.existsSync(texturesDir)) {
            return [];
        }
        
        // 读取目录中的所有文件
        const files = await fs.readdir(texturesDir);
        const textures = [];
        
        // 遍历所有 .json 文件
        for (const file of files) {
            if (file.endsWith('.json')) {
                try {
                    const configPath = path.join(texturesDir, file);
                    const data = await fs.readFile(configPath, 'utf-8');
                    const textureConfig = JSON.parse(data);
                    textures.push(textureConfig);
                } catch (error) {
                    console.warn(`⚠️ 读取贴图配置失败 (${file}):`, error.message);
                }
            }
        }
        
        // 按创建时间排序
        textures.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
        
        return textures;
    } catch (error) {
        console.error('❌ 获取贴图列表失败:', error);
        return [];
    }
}

/**
 * 更新贴图的引用记录
 * @param {string} texturesDir - 贴图目录路径
 * @param {string} textureNameOrId - 贴图名称或ID（displayName或id）
 * @param {string} materialDisplayName - 材质显示名称
 * @param {string} action - 'add' 或 'remove'
 * @returns {Promise<Object|null>} 更新后的贴图配置
 */
async function updateTextureReference(texturesDir, textureNameOrId, materialDisplayName, action) {
    // 查找贴图（支持通过displayName或id查找）
    const textures = await getAllTextures(texturesDir);
    const texture = textures.find(t => 
        t.displayName === textureNameOrId || 
        t.name === textureNameOrId ||
        t.id === textureNameOrId
    );
    
    if (!texture) {
        console.warn(`⚠️ 未找到贴图: ${textureNameOrId}`);
        return null;
    }
    
    // 确保 referencedBy 数组存在
    if (!texture.referencedBy) {
        texture.referencedBy = [];
    }
    
    if (action === 'add') {
        // 添加引用（避免重复）
        if (!texture.referencedBy.includes(materialDisplayName)) {
            texture.referencedBy.push(materialDisplayName);
            console.log(`   ✓ 添加贴图引用: ${texture.displayName} ← ${materialDisplayName}`);
        }
    } else if (action === 'remove') {
        // 移除引用
        const beforeCount = texture.referencedBy.length;
        texture.referencedBy = texture.referencedBy.filter(name => name !== materialDisplayName);
        if (beforeCount > texture.referencedBy.length) {
            console.log(`   ✓ 移除贴图引用: ${texture.displayName} ✗ ${materialDisplayName}`);
        }
    }
    
    // 更新引用计数
    texture.referenceCount = texture.referencedBy.length;
    
    // 保存更新
    await writeTextureConfig(texturesDir, texture.id, texture);
    
    return texture;
}

/**
 * 同步材质的所有贴图引用
 * @param {string} texturesDir - 贴图目录路径
 * @param {Object} materialData - 材质数据
 * @param {Object} oldMaterialData - 旧材质数据（更新时提供）
 * @returns {Promise<void>}
 */
async function syncMaterialTextureReferences(texturesDir, materialData, oldMaterialData = null) {
    const materialDisplayName = materialData.displayName;
    
    // 所有可能包含贴图的字段
    const textureFields = [
        'map', 'normalMap', 'bumpMap', 'roughnessMap', 'metalnessMap',
        'aoMap', 'emissiveMap', 'displacementMap', 'alphaMap'
    ];
    
    // 收集当前材质使用的贴图
    const currentTextures = new Set();
    textureFields.forEach(field => {
        if (materialData[field]) {
            currentTextures.add(materialData[field]);
        }
    });
    
    // 收集旧材质使用的贴图（如果是更新操作）
    const oldTextures = new Set();
    if (oldMaterialData) {
        textureFields.forEach(field => {
            if (oldMaterialData[field]) {
                oldTextures.add(oldMaterialData[field]);
            }
        });
    }
    
    // 添加新增的贴图引用
    for (const textureName of currentTextures) {
        if (!oldTextures.has(textureName)) {
            await updateTextureReference(texturesDir, textureName, materialDisplayName, 'add');
        }
    }
    
    // 移除不再使用的贴图引用
    for (const textureName of oldTextures) {
        if (!currentTextures.has(textureName)) {
            await updateTextureReference(texturesDir, textureName, materialDisplayName, 'remove');
        }
    }
}

/**
 * 移除材质的所有贴图引用
 * @param {string} texturesDir - 贴图目录路径
 * @param {Object} materialData - 材质数据
 * @returns {Promise<void>}
 */
async function removeMaterialTextureReferences(texturesDir, materialData) {
    const materialDisplayName = materialData.displayName;
    
    // 所有可能包含贴图的字段
    const textureFields = [
        'map', 'normalMap', 'bumpMap', 'roughnessMap', 'metalnessMap',
        'aoMap', 'emissiveMap', 'displacementMap', 'alphaMap'
    ];
    
    // 移除所有贴图引用
    for (const field of textureFields) {
        if (materialData[field]) {
            await updateTextureReference(texturesDir, materialData[field], materialDisplayName, 'remove');
        }
    }
}

module.exports = {
    readTextureConfig,
    writeTextureConfig,
    deleteTextureConfig,
    getAllTextures,
    updateTextureReference,
    syncMaterialTextureReferences,
    removeMaterialTextureReferences
};

